package js.web.center.core;

import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import javax.script.ScriptException;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.eclipse.jetty.server.session.DefaultSessionCacheFactory;
import org.eclipse.jetty.server.session.SessionCache;
import org.eclipse.jetty.server.session.SessionDataStoreFactory;
import org.eclipse.jetty.webapp.WebAppContext;

import com.alibaba.fastjson.JSONObject;

import js.web.center.core.config.JsWebConfig;
import js.web.center.netty.JsWebSocketMain;
import js.web.center.netty.config.JsWebSocketConstant;
import js.web.center.netty.thread.JsWebSocketUpdateThread;
import js.web.center.script.core.JsWebScriptEngineCore;
import js.web.center.script.thread.JsWebScriptThread;
import js.web.center.thread.JsWebSessionThread;
import js.web.center.thread.JsWebSocketServerThread;
import js.web.center.utils.JsWebSyncCtrlUtils;
import js.web.center.web.JsWebServer;
import js.web.center.web.session.JsWebSessionDataStoreFactory;
/**
 * 项目入口
 * @author dowell
 *
 */
public class Main {

	public static void main(String[] args) {
		PropertyConfigurator.configure("log4j.properties");
		Calendar calendar=Calendar.getInstance();
		SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd hh:mm:SS");
		final Logger logger=Logger.getLogger("启动");
		String printInfo="";
		printInfo+="\n===============================================";
		printInfo+="\n-======== JsWeb网络版本";
		printInfo+="\n-======== Java依赖版本：1.8.x";
		printInfo+="\n-======== 当前版本号：0.0.2";
		printInfo+="\n-======== 启动时间："+dateFormat.format(calendar.getTime());
		JsWebScriptEngineCore.basePath="script/";
		JsWebConfig.rootPath = System.getProperty("user.dir");
		JsWebScriptEngineCore engineCore=new JsWebScriptEngineCore();
		try {
			engineCore.init("config");
			engineCore.function("init");
			engineCore.appParams("logger", logger);
			JsWebSyncCtrlUtils.executor=new ThreadPoolExecutor(10, JsWebConfig.poolSize, JsWebConfig.poolIdle, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
			printInfo+="\n-======== Web http服务器：【"+(JsWebConfig.httpServerOpen==1?"开启】":"关闭】");
			if(JsWebConfig.httpServerOpen==1){
				printInfo+="\n-======== Web http 监听："+JsWebConfig.port;
				printInfo+="\n-======== Sesssion 过期时间："+JsWebConfig.webSessionOutTime;
				printInfo+="\n-======== Sessoion 更新线程时间："+JsWebConfig.getSessionUpdateTime;
				if(JsWebConfig.lostErrorUrl.length()>0){
					printInfo+="\n-======== 404 跳转界面："+JsWebConfig.lostErrorUrl;
				}else{
					printInfo+="\n-======== 404 跳转界面：无";
				}
			}
			printInfo+="\n-======== WebSocket服务器：【"+(JsWebConfig.websocketOpen==1?"开启】":"关闭】");
			if(JsWebConfig.websocketOpen==1){
				printInfo+="\n-======== WebSocket监听："+JsWebConfig.webSocket;
				printInfo+="\n-======== WebSocket访问路径："+JsWebConfig.webSocketPath;
			}
			printInfo+="\n-======== 单用户保存数据长度："+JsWebConfig.maxSessionNum;
			printInfo+="\n-======== socket服务器:【"+(JsWebConfig.socketOpen==1?"开启】":"关闭】");
			if(JsWebConfig.socketOpen==1){
				printInfo+="\n-======== socket端口："+JsWebConfig.socketPort;
				printInfo+="\n-======== socket缓冲区大小："+JsWebConfig.socketBufLength;
				printInfo+="\n-======== 最大包大小："+JsWebSocketConstant.socketMaxLength;
			}
			
			JsWebSyncCtrlUtils.executor.execute(new JsWebSessionThread());
			JsWebSyncCtrlUtils.executor.execute(new JsWebScriptThread());
			if(JsWebConfig.websocketOpen==1){
				JsWebSyncCtrlUtils.executor.execute(new JsWebSocketServerThread());
			}
			printInfo+="\n-======== 开始初始化HttpServlet：";
			if(JsWebConfig.httpServerOpen==1){
				DefaultSessionCacheFactory cacheFactory = new DefaultSessionCacheFactory();
		        cacheFactory.setEvictionPolicy(SessionCache.EVICT_ON_SESSION_EXIT);
		        SessionDataStoreFactory storeFactory = new JsWebSessionDataStoreFactory();
				try {
					JsWebServer jsWebServer=new JsWebServer(JsWebConfig.port, 0, -1, cacheFactory, storeFactory);
					WebAppContext addWebAppContext = jsWebServer.addWebAppContext(JsWebConfig.jsWebStaticName, "");
					addWebAppContext.setMaxFormContentSize(20000000);
					engineCore.appParams("webAppContext", addWebAppContext);
					jsWebServer.start();
					String mapStr=engineCore.function("classMap").toString();
					JSONObject jsonObject=JSONObject.parseObject(mapStr);
					Iterator<Entry<String, Object>> iterator = jsonObject.entrySet().iterator();
					while(iterator.hasNext()){
						Entry<String, Object> next = iterator.next();
						printInfo+="\n-======== 类："+next.getKey()+"【路径："+next.getValue().toString()+"】";
						addWebAppContext.addServlet(next.getKey(), next.getValue().toString());
					}
				} catch (Exception e) {
					logger.error("main ERROR:{}",e);
				}
			}
			printInfo+="\n-======== 程序正在启动,请稍等...";
			printInfo+="\n===============================================";
			logger.info(printInfo);
			if(JsWebConfig.socketOpen==1){
				JsWebSocketMain jsWebSocketMain=new JsWebSocketMain();
				try {
					jsWebSocketMain.init();
				} catch (InterruptedException e) {
					logger.error("main ERROR:{}",e);
				}
				JsWebSyncCtrlUtils.executor.execute(new JsWebSocketUpdateThread());
			}
		} catch (FileNotFoundException e) {
			logger.error("main ERROR:{}",e);
		} catch (ScriptException e) {
			logger.error("main ERROR:{}",e);
		} catch (NoSuchMethodException e) {
			logger.error("main ERROR:{}",e);
		}
	}
}